function gadget:GetInfo()
  return {
    name      = "Construction animation",
    desc      = "Draws units in construction and scaffoldings",
    author    = "Rafal",
    date      = "Jan 2012",
    license   = "GNU GPL, v2 or later",
    layer     = 0,
    enabled   = true  --  loaded by default?
  }
end

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- COMMON

-- CONFIG

local drawScaffolding = true

local defaultWireframeHeight = 8.0
local wireframeSpeedMult = 4.0
local wireframeColor = { 0.25, 0.25, 0.25, 1.0 }
local wireframeLineScale = 0.8  --scaled with distance

local scaffoldingBuildTime = 1.0
local scaffoldingRemovalTime = 0.5
local scaffoldingSideTexture = "unittextures\other\scaffolding_side.png"
local scaffoldingTopTexture  = "unittextures\other\scaffolding_top.png"
local scaffoldingScale = 10.0
local scaffoldingAspect = 1.5

-- COMMON
--------------------------------------------------------------------------------
if (gadgetHandler:IsSyncedCode()) then
--------------------------------------------------------------------------------
-- SYNCED

local spGetUnitDefID  = Spring.GetUnitDefID
local spGetUnitHealth = Spring.GetUnitHealth
local spSetUnitNoDraw = Spring.SetUnitNoDraw

--------------------------------------------------------------------------------



--------------------------------------------------------------------------------

function gadget:Initialize()
	local units = Spring.GetAllUnits()
	for _,unitID in ipairs(units) do
		local udID = spGetUnitDefID(unitID)
    local _,_,_,_,buildProgress = spGetUnitHealth(unitID)
    local builderID = (buildProgress < 1.0) and -1 or nil

		gadget:UnitCreated(unitID, udID, nil, builderID)
	end
end

function gadget:UnitCreated(unitID, unitDefID, teamID, builderID)
  --if (health >= 1.0) then
  --if (builderID) then
    spSetUnitNoDraw(unitID, true)
    SendToUnsynced("Synced:UnitCreated", unitID, unitDefID)
  --end
end

function gadget:UnitFinished(unitID, unitDefID, teamID)
  --spSetUnitNoDraw(unitID, false)
  --SendToUnsynced("Synced:UnitFinished", unitID)
end

function gadget:UnitDestroyed(unitID, unitDefID, teamID, attackerID, attackerDefID, attackerTeamID)
  SendToUnsynced("Synced:UnitDestroyed", unitID)
end

function gadget:GameFrame (frameNum)

end

-- SYNCED
--------------------------------------------------------------------------------
else
--------------------------------------------------------------------------------
-- UNSYNCED

local spGetCameraPosition   = Spring.GetCameraPosition
local spGetCameraDirection  = Spring.GetCameraDirection
local spGetSpectatingState  = Spring.GetSpectatingState
local spGetMyTeamID         = Spring.GetMyTeamID
local spIsUnitInView        = Spring.IsUnitInView
local spIsUnitVisible       = Spring.IsUnitVisible
local spGetUnitViewPosition = Spring.GetUnitViewPosition
local spGetUnitHealth       = Spring.GetUnitHealth
local urSetUnitLuaDraw      = Spring.UnitRendering.SetUnitLuaDraw
local glGetViewSizes        = gl.GetViewSizes
local glColor               = gl.Color
local glLighting            = gl.Lighting
local glMaterial            = gl.Material
local glLineWidth           = gl.LineWidth
local glPolygonMode         = gl.PolygonMode
local glDepthTest           = gl.DepthTest
local glDepthMask           = gl.DepthMask
local glCulling             = gl.Culling
local glClipPlane           = gl.ClipPlane
local glUnit                = gl.Unit
local glUnitRaw             = gl.UnitRaw
local GL_FRONT_AND_BACK     = GL.FRONT_AND_BACK
local GL_LINE               = GL.LINE
local GL_FILL               = GL.FILL
local GL_LEQUAL             = GL.LEQUAL
local gameSpeed             = Game.gameSpeed

local max                   = math.max
local abs                   = math.abs

--------------------------------------------------------------------------------

local unitsBeingBuilt = {}
local constructionData = {}

local scaffoldingBuildStep = 1.0 / (scaffoldingBuildTime * gameSpeed)
local scaffoldingRemovalStep = 1.0 / (scaffoldingRemovalTime * gameSpeed)


local function glColor4fv (color)
  glColor(color[1], color[2], color[3], color[4])
end


local function CreateConstructionData(udID)
  local ud = UnitDefs[udID]
  --local params = UnitDefs[udID].myCustomParams
  local wireframeHeight = ud.myCustomParams.constructionWireframe
  if (type(wireframeHeight) ~= "number") then
    wireframeHeight = wireframeHeight and defaultWireframeHeight or 0
  end

  local data = {}
  data.wireframeHeight = wireframeHeight
  data.wireframeFactor = wireframeHeight / wireframeSpeedMult
  data.totalHeight = ud.maxy + data.wireframeFactor  --ud.height + ud.miny
  data.maxY = ud.maxy
  constructionData[udID] = data
end

--------------------------------------------------------------------------------

function gadget:UnitCreated(unitID, unitDefID)
  if (not constructionData[unitDefID]) then
    CreateConstructionData(unitDefID)
  end

  urSetUnitLuaDraw(unitID, true)
  unitsBeingBuilt[unitID] = {
    --udID = unitDefID,
    defData = constructionData[unitDefID],
  }
end

function gadget:UnitFinished(unitID)
  urSetUnitLuaDraw(unitID, false)
  unitsBeingBuilt[unitID] = nil
end

function gadget:UnitDestroyed(unitID)
  unitsBeingBuilt[unitID] = nil
end

function gadget:Initialize()
	gadgetHandler:AddSyncAction("Synced:UnitCreated", gadget.UnitCreated)
  gadgetHandler:AddSyncAction("Synced:UnitFinished", gadget.UnitFinished)
  gadgetHandler:AddSyncAction("Synced:UnitDestroyed", gadget.UnitDestroyed)
end

function gadget:Shutdown()
	gadgetHandler:RemoveSyncAction("Synced:UnitCreated")
	gadgetHandler:RemoveSyncAction("Synced:UnitFinished")
	gadgetHandler:RemoveSyncAction("Synced:UnitDestroyed")
  --for _, list in pairs(fireArcLists) do
  --  glDeleteList(list)
  --end
end

local drawPhase
local drawData
function gadget:DrawUnit(unitID, drawMode)
  --Spring.Echo("DrawUnit: " .. tostring(unitID) .. " " .. tostring(drawMode) .. " " .. tostring(customDraw))
  if (drawPhase == 1) then
    glCulling(false)
    glClipPlane(1, 0, -1, 0, drawData.heightBuilt)
  elseif (drawPhase == 2) then
    glClipPlane(1, 0, 1, 0, -drawData.heightBuilt)
    if (drawData.wireframeHeightBuilt < drawData.defData.maxY) then
      glClipPlane(2, 0, -1, 0, drawData.wireframeHeightBuilt)
    else
      glClipPlane(2, false)
    end
  end
end


local visibleUnits
local function GetVisibleUnitsToDraw (visibilityFunc)
  for unitID, data in pairs(unitsBeingBuilt) do
    if (visibilityFunc(unitID)) then
      visibleUnits[unitID] = data
    end
  end
end


function gadget:DrawWorld()
  visibleUnits = {}
  local _,fullView = spGetSpectatingState()
  if (fullView) then
    GetVisibleUnitsToDraw (spIsUnitInView)
  else
    CallAsTeam(spGetMyTeamID(), GetVisibleUnitsToDraw, spIsUnitVisible)
  end

  if (next(visibleUnits)) then
    --gl.Blending(false)
    --gl.Culling(GL.BACK)
    --gl.AlphaTest(GL.GREATER, 0.5)
    glDepthTest(GL_LEQUAL)
    glDepthMask(true)
    glCulling(false)
    --gl.Color(0, 1, 0, 1.0)

    drawPhase = 1

    for unitID, data in pairs(visibleUnits) do
      local defData = data.defData
      local _,_,_,_,buildProgress = spGetUnitHealth(unitID)
      local totalHeightBuilt = buildProgress * defData.totalHeight
      data.heightBuilt = totalHeightBuilt - defData.wireframeFactor

      if (data.heightBuilt > 0) then
        drawData = data
        glUnit(unitID, false)
      end
    end

    drawPhase = 2

    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
    glLighting(true)
    
    glColor4fv(wireframeColor)
    glMaterial({ ambidiff = wireframeColor, })

    local _,viewSizeY = glGetViewSizes()
    local lineScale = wireframeLineScale * viewSizeY
    local cx, cy, cz = spGetCameraPosition()
    local cA, cB, cC = spGetCameraDirection()
    local cD = -(cA * cx + cB * cy + cC * cz)
    
    for unitID, data in pairs(visibleUnits) do
      local defData = data.defData
      if (defData.wireframeHeight > 0) then
        local ux, uy, uz = spGetUnitViewPosition(unitID, true)
        local distToCameraPlane = abs(cA * ux + cB * uy + cC * uz + cD)
        local lineWidth = lineScale / max(16, distToCameraPlane)
        
        glLineWidth(lineWidth)   
      
        local wireframeStart = (data.heightBuilt >= 0) and data.heightBuilt or (data.heightBuilt * wireframeSpeedMult)
        data.wireframeHeightBuilt = wireframeStart + defData.wireframeHeight

        drawData = data
        glUnit(unitID, true)
      end
    end

    drawPhase = nil

    glClipPlane(1, false)
    glClipPlane(2, false)
    glLineWidth(1.0)
    glLighting(false)
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)

    gl.PushMatrix()

    gl.Translate(0.0, 300, 0.0)
    gl.Scale(200, 200, 200)

    local vertices = {
      { v = {  0, 0,  0   }},
      { v = {  0, 0,  2   }},
      { v = {  1, 0,  0.5 }},
      { v = {  1, 0,  1.5 }},
      { v = {  2, 0,  0   }},
      { v = {  2, 0,  2   }},
    }

    glColor(1, 0, 0, 1)
    gl.Shape(GL.QUAD_STRIP, vertices)

    gl.PopMatrix()

    glCulling(true)
    glColor(1, 1, 1, 1)
  end
end

-- UNSYNCED
end